package org.apache.ocean;

import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.ConstantScoreRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.ocean.server.FieldType;

/**
 *
 * @author jasonr
 */
// TODO: unit test OceanQueryParser
public class OceanQueryParser extends QueryParser {
  IndexSchema indexSchema;
  
  public OceanQueryParser(IndexSchema indexSchema) {
    super(indexSchema.getDefaultSearchFieldName(), indexSchema.getQueryAnalyzer());
    setLowercaseExpandedTerms(false);
  }
  
  public static Query parse(String queryString, IndexSchema indexSchema) throws ParseException {
    return new OceanQueryParser(indexSchema).parse(queryString);
  }
  
  protected Query getFieldQuery(String field, String queryText) throws ParseException {
    return super.getFieldQuery(field, queryText);
  }
  
  protected Query getPrefixQuery(String field, String termStr) throws ParseException {
    if (getLowercaseExpandedTerms()) {
      termStr = termStr.toLowerCase();
    }
    // TODO: toInternal() won't necessarily work on partial
    // values, so it looks like i need a getPrefix() function
    // on fieldtype?  Or at the minimum, a method on fieldType
    // that can tell me if I should lowercase or not...
    // Schema could tell if lowercase filter is in the chain,
    // but a more sure way would be to run something through
    // the first time and check if it got lowercased.

    // (sortable numeric types don't do prefixes, but can do range queries)
    Term term = new Term(field, termStr);
    return new ConstantScorePrefixQuery(term);
  }
  
  protected Query getRangeQuery(String field, String part1, String part2, boolean inclusive) throws ParseException {
    FieldType fieldType = indexSchema.getFieldType(field);
    return new ConstantScoreRangeQuery(
      field,
      "*".equals(part1) ? null : fieldType.toInternal(part1),
      "*".equals(part2) ? null : fieldType.toInternal(part2),
      inclusive, inclusive);
  }
}
